import xtriui
import uix
import uthread
import util
import blue
import types
import trinity
import dbg
import uicls
import uiconst
import uiutil

class Hint(uicls.HintCore):
    __guid__ = 'uicls.Hint'

    def Prepare_(self):
        self.sr.textobj = uicls.Label(text='', parent=self, left=8, top=3, align=uiconst.TOPLEFT, letterspace=1, fontsize=10, state=uiconst.UI_DISABLED)
        border = uicls.Frame(parent=self, frameConst=uiconst.FRAME_BORDER1_CORNER5, state=uiconst.UI_DISABLED, color=(1.0, 1.0, 1.0, 0.25))
        frame = uicls.Frame(parent=self, color=(0.0, 0.0, 0.0, 0.75), frameConst=uiconst.FRAME_FILLED_CORNER4, state=uiconst.UI_DISABLED)



    def Prepare_HintStr_(self, hint):
        return uiutil.UpperCase(hint)




class BigHint(uicls.Container):
    __guid__ = 'xtriui.BigHint'

    def init(self):
        self.hint = ''
        self.sr.hint = ''
        self.sr.header = ''
        self.sr.x = 0
        self.sr.y = 0
        self.sr.maxWidth = 256
        self.sr.hintsave = None



    def _OnClose(self):
        for each in uicore.layer.main.children[:]:
            if ((each.name == 'bighint') and ((each is not None) and (not each.destroyed))):
                each.Close()




    def _OnMouseEnter(self, *args):
        self.GetBiggy().ShowHint(self, self.sr.header, self.sr.hint, self.sr.x, self.sr.y)
        self.sr.hintsave = self.sr.hint
        self.sr.hint = ''



    def _OnMouseExit(self, *args):
        self.GetBiggy().HideHint()
        if self.sr.hintsave:
            self.sr.hint = self.sr.hintsave
            self.sr.hintsave = None
        self.hintsave = None



    def GetBiggy(self):
        for each in uicore.layer.main.children[:]:
            if ((each.name == 'bighint') and ((each is not None) and (not each.destroyed))):
                return each

        bighint = xtriui._BigHint(blue.os.LoadObject('res:/UI/Component/hint_big.blue'))
        bighint.Startup()
        return bighint




class _BigHint(uicls.Container):
    __guid__ = 'xtriui._BigHint'

    def init(self):
        self.name = 'bighint'



    def Startup(self):
        self.sr.headerparent = uiutil.GetChild(self, 'headerparent')
        self.sr.maintext = uicls.Label(text='', parent=uiutil.GetChild(self, 'content'), left=8, top=18, autowidth=False, fontsize=12, state=uiconst.UI_DISABLED, color=(1.0, 1.0, 1.0, 0.75))
        self.sr.header = uicls.Label(text='', parent=self.sr.headerparent, left=8, top=2, letterspace=2, autowidth=False, fontsize=9, linespace=8, state=uiconst.UI_DISABLED, color=(1.0, 1.0, 1.0, 0.75), idx=0)
        uicls.Fill(parent=self, color=(0.0, 0.0, 0.0, 1.0))
        uicore.layer.main.children.append(self)



    def ShowHint(self, button, header = '', main = '', x = 0, y = 0):
        if header:
            self.sr.headerparent.state = uix.UI_DISABLED
            self.sr.header.width = button.sr.maxWidth
            self.sr.header.text = uiutil.UpperCase(header)
            headerwidth = self.sr.header.textwidth
            self.sr.headerparent.height = (self.sr.header.textheight + 4)
        else:
            self.sr.headerparent.state = uix.UI_HIDDEN
            headerwidth = 0
        self.sr.maintext.top = (self.sr.headerparent.height + 4)
        self.sr.maintext.width = button.sr.maxWidth
        self.sr.maintext.text = main
        mainwidth = self.sr.maintext.textwidth
        uiutil.SetOrder(self, 0)
        self.state = uix.UI_DISABLED
        self.width = (min(button.sr.maxWidth, max(headerwidth, mainwidth)) + 24)
        if ((((x + button.width) + button.absoluteLeft) + self.width) < eve.triapp.uilib.desktop.width):
            self.left = ((x + button.width) + button.absoluteLeft)
        else:
            self.left = ((x - self.width) + button.absoluteLeft)
        self.top = (y + button.absoluteTop)
        self.height = 48
        uthread.new(uicore.effect.MorphUI, self, 'height', ((self.sr.maintext.height + self.sr.headerparent.height) + 12), 100.0, 0)



    def HideHint(self):
        self.state = uix.UI_HIDDEN




class BubbleHint(uicls.Container):
    __guid__ = 'xtriui.BubbleHint'

    def init(self):
        self.sr.showExtended = None
        self.extendedHint = ''
        self.collapsedHint = ''
        self.expanded = 0
        self.name = 'bubblehint'
        u = blue.os.LoadObject('res:/UI/Component/bubblehint.blue')
        u.left = u.top = u.width = u.height = 0
        u.align = uix.UI_ALCLIENT
        self.children.append(u)
        self.content = uicls.Container(name='content', parent=self, idx=0, width=2, height=4, left=2, top=4)
        for each in u.children:
            setattr(self.sr, each.name, each)

        uicls.Fill(parent=u, color=(0.0, 0.0, 0.0, 0.8), left=2, top=2, width=2, height=2)
        self.state = uiconst.UI_NORMAL



    def ShowHint(self, hint, pointer = 0, textMaxWidth = 200):
        uix.Flush(self.content)
        if (type(hint) != types.ListType):
            hint = [hint]
        maxWidth = 0
        for entryData in hint:
            if (entryData in ('<line>', '<dotline>')):
                uicls.Line(parent=self.content, align=uiconst.TOTOP, height=1)
                continue
            entry = HintEntry(uicls.Container(name='entryparent', align=uiconst.TOTOP))
            self.content.children.append(entry)
            entry.Startup(entryData, textMaxWidth)
            entry.OnMouseEnter = self.DecoEntryMouseEnter(getattr(entry, 'OnMouseEnter', None))
            entry.OnMouseExit = self.DecoEntryMouseExit(getattr(entry, 'OnMouseExit', None))

        self.width = (max([ each.width for each in self.content.children ]) + 12)
        self.height = (sum([ each.height for each in self.content.children ]) + 8)
        self.SetPointer(pointer)
        self.data = (hint, pointer)



    def DecoEntryMouseExit(self, f):

        def OnMouseExit(entry, *args):
            sub = getattr(entry.sr, 'sub', None)
            if sub:
                if (eve.triapp.uilib.mouseOver != sub):
                    self.ClearSub(entry)
            elif (type(f) in (list, tuple)):
                (callback, passedArgs,) = f
                callback(passedArgs, entry, *args)
            if (f is not None):
                f(entry, *args)


        return OnMouseExit



    def DecoEntryMouseEnter(self, f):

        def OnMouseEnter(entry, *args):
            self.Expand()
            if (f is None):
                pass
            elif (type(f) in (list, tuple)):
                (callback, passedArgs,) = f
                callback(passedArgs, entry, *args)
            else:
                f(entry, *args)


        return OnMouseEnter



    def OnEntryMouseExit(self, entry, *args):
        if (getattr(entry, 'OnMouseExit', None) not in (None, self.OnEntryMouseExit)):
            entry.OnMouseExit(entry, *args)
        elif (getattr(entry, '_OnMouseExit', None) is not None):
            entry._OnMouseExit(entry, *args)



    def OnEntryMouseEnter(self, entry, *args):
        self.Expand()
        if (getattr(entry, 'OnMouseEnter', None) not in (None, self.OnEntryMouseEnter)):
            entry.OnMouseEnter(entry, *args)
        elif (getattr(entry, '_OnMouseEnter', None) is not None):
            entry._OnMouseEnter(entry, *args)



    def _OnMouseEnter(self, *args):
        self.Expand()



    def Expand(self):
        func = self.sr.Get('ExpandHint', None)
        if func:
            func(self, 1)



    def _ShowSubhint(self, passedArgs, entry):
        if not getattr(entry.sr, 'hilite', None):
            entry.sr.hilite = uicls.Fill(parent=entry)
        self.ClearSubs()
        uiutil.SetOrder(self.parent, 0)
        for each in self.content.children:
            if ((each != entry) and (getattr(each, 'sr', None) and getattr(each.sr, 'hilite', None))):
                each.sr.hilite.state = uix.UI_HIDDEN

        entry.sr.hilite.state = uix.UI_DISABLED
        if (len(passedArgs) == 2):
            (funcName, args,) = passedArgs
            func = getattr(self, funcName, None)
            if not func:
                uix.LogError('Unsupported dynamic function in bubblehint', funcName)
                return 
            hint = func(*args)
        else:
            (hint,) = passedArgs
        bubble = xtriui.BubbleHint(uicls.Container(parent=self.parent, name='subbubblehint', align=uiconst.TOPLEFT, width=0, height=0, idx=0, state=uiconst.UI_PICKCHILDREN))
        bubble.ShowHint(hint, None, 100)
        if ((not self) or self.destroyed):
            return 
        self.sr.sub = bubble
        if self.parent:
            (pl, pt, pw, ph,) = self.parent.GetAbsolute()
            (ll, lt, lw, lh,) = entry.GetAbsolute()
            bubble.left = (((ll - pl) + lw) - 6)
            bubble.top = ((lt - pt) - 2)



    def SetPointer(self, pointer, reposition = 1):
        self.sr.t1.width = self.sr.b1.width = ((self.width - 8) / 2)
        self.sr.t2.width = self.sr.b2.width = ((self.width - 8) - self.sr.t1.width)
        self.sr.l1.height = self.sr.r1.height = ((self.height - 8) / 2)
        self.sr.l2.height = self.sr.r2.height = ((self.height - 8) - self.sr.l1.height)
        self.sr.p0.state = uix.UI_HIDDEN
        self.sr.p1.state = uix.UI_HIDDEN
        self.sr.p2.state = uix.UI_HIDDEN
        self.sr.p3.state = uix.UI_HIDDEN
        self.sr.p4.state = uix.UI_HIDDEN
        self.sr.p5.state = uix.UI_HIDDEN
        self.autoPos = uix.AUTOPOSNONE
        if (pointer is not None):
            p = self.sr.Get(('p%s' % pointer), None)
            p.state = uix.UI_DISABLED
            if (pointer in (0, 3)):
                left = ((self.parent.width / 2) + 2)
            elif (pointer in (2, 5)):
                left = (((self.parent.width / 2) - self.width) - 2)
            elif (pointer in (1, 4)):
                left = (((self.parent.width - self.width) / 2) + 1)
            sidePointerIdx = pointer
            if (pointer in (0, 1, 2)):
                top = (((self.parent.height / 2) - self.height) - 18)
                (leftside, rightside,) = (self.sr.b1, self.sr.b2)
            elif (pointer in (3, 4, 5)):
                top = ((self.parent.height / 2) + 20)
                (leftside, rightside,) = (self.sr.t1, self.sr.t2)
                sidePointerIdx -= 3
            leftside.width = [4,
             (((self.width - 8) / 2) - 2),
             (self.width - 17)][sidePointerIdx]
            rightside.width = (((self.width - 8) - leftside.width) - 4)
            if reposition:
                self.left = left
                self.top = top
        elif (util.GetAttrs(self, 'parent') is not None):
            self.left = ((self.parent.width / 2) + 12)
            self.top = ((self.parent.height / 2) - 8)



    def GetEntry(self, id_):
        for each in self.content.children:
            if (util.GetAttrs(each, 'data', 'id') == id_):
                return each




    def Offset(self, x, y, pointer):
        self.SetPointer(pointer, 0)
        self.sr.left = self.left
        self.sr.top = self.top
        self.left += x
        self.top += y



    def ResetOffset(self):
        if self.sr.Get('left', None):
            self.left = self.sr.left
            self.top = self.sr.top
        if getattr(self, 'data', None):
            self.SetPointer(self.data[1])



    def GetBubbleHint(self, *args):
        return sm.GetService('systemmap').GetBubbleHint(*args)



    def ClearSubs(self):
        if self.sr.Get('sub', None):
            self.sr.sub.Close()
            self.sr.sub = None



    def _OnClose(self):
        self.ClearSubs()




class HintEntry(uicls.Container):
    __guid__ = 'xtriui.HintEntry'

    def Startup(self, data, textMaxWidth):
        self.data = data
        self.textMaxWidth = textMaxWidth
        self.Refresh()



    def Refresh(self):
        data = self.data
        uix.Flush(self)
        textMaxWidth = self.textMaxWidth
        if isinstance(data, basestring):
            data = HintEntryData(data)
        elif isinstance(data, tuple):
            (text, (event, func, args,),) = data
            data = HintEntryData(text, event=event, func=func, args=args)
        if data.menuGetter:
            self.state = uix.UI_NORMAL
            self.GetMenu = data.menuGetter
        label = uicls.Label(text=data.text, parent=self, left=5, top=1, letterspace=1, fontsize=8, linespace=8, state=uiconst.UI_DISABLED, uppercase=1, idx=0)
        self.sr.label = label
        if (label.textwidth > textMaxWidth):
            label.busy = 1
            label.autowidth = 0
            label.width = textMaxWidth
            label.busy = 0
            label.text = data.text
        self.width = label.textwidth
        self.height = (label.textheight + 1)
        self.name = data.text

        def AddIcon(iconNum, left = -1):
            uicls.Icon(icon=iconNum, parent=self, pos=(left,
             -2,
             16,
             16), align=uiconst.TOPRIGHT, idx=0, state=uiconst.UI_DISABLED)
            self.width += 14


        if data.func:
            setattr(self, data.event, (getattr(self, data.func, None), data.args))
            self.state = uix.UI_NORMAL
            if (data.func == 'ShowSubhint'):
                AddIcon(iconNum='ui_38_16_127')
            elif (data.func == 'ShowInfo'):
                AddIcon(iconNum='ui_38_16_126')
            else:
                if (data.func == 'OpenAssets'):
                    AddIcon(iconNum='ui_38_16_125')
        if data.talking:
            AddIcon(iconNum='ui_38_16_91', left=0)



    def GetBubble(self):
        return self.FindParentByName('bubblehint')



    def OnMouseEnter(self, *etc):
        self.sr.label.oldText = self.sr.label.text
        self.sr.label.text = ('<b>%s</b>' % self.sr.label.text)


    OnMouseEnter = uiutil.ParanoidDecoMethod(OnMouseEnter, ('sr', 'label'))

    def OnMouseExit(self, *etc):
        if util.GetAttrs(self, 'sr', 'label', 'oldText'):
            self.sr.label.text = self.sr.label.oldText


    OnMouseExit = uiutil.ParanoidDecoMethod(OnMouseExit, ('sr',))

    def ShowInfo(self, passedArgs, *args):
        (typeID, itemID,) = passedArgs
        sm.GetService('info').ShowInfo(typeID, itemID)



    def ShowSubhint(self, passedArgs, entry):
        bubble = self.GetBubble()
        if (bubble is None):
            return 
        if (len(passedArgs) == 2):
            uthread.new(bubble._ShowSubhint, passedArgs, entry)
        else:
            bubble._ShowSubhint(passedArgs, entry)



    def OpenAssets(self, passedArgs, *args):
        (stationID,) = passedArgs
        sm.GetService('assets').Show(stationID)



    def OpenAddressbook(self, contactType, *args):
        ab = sm.GetService('addressbook')
        ab.Show()
        ab.ShowContacts(contactType)




class HintEntryData():
    __guid__ = 'hint.EntryData'

    def __init__(self, text, id = None, event = None, func = None, args = None, menuGetter = None, talking = False):
        self.text = text
        self.event = event
        self.func = func
        self.args = args
        self.menuGetter = menuGetter
        self.talking = talking
        self.id = id




